home *** CD-ROM | disk | FTP | other *** search
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <tos.h>
- #include <aes.h>
- #include "pktdrv.h"
- #include "ip.h"
- #include "arp.h"
- #include "icmp.h"
- #include "netdb.h"
- #include "queue.h"
- #include "inetcust.h"
-
- #include "cookie.h"
- #include "nettrace.h"
-
- #define Bconws(x) dpy = x;while(*dpy)(Bconout(2,*dpy++))
-
- static char *dpy;
-
- #define noDEBUG
- #define noDEBUGP
- #define noDEBUGA
- #define noDEBUGPKT
- #define noDEBUGF
-
- #define AMASK 0x80L
- #define AADDR 0x00L
- #define BMASK 0xC0L
- #define BADDR 0x80L
- #define CMASK 0xE0L
- #define CADDR 0xC0L
-
- #ifdef DEBUGF
- static char str[100];
- #endif
-
- extern long q_disint(void);
- extern long q_enabint(void);
- extern long p_disint(void);
- extern long p_enabint(void);
-
- INADDR lcl_inaddr = 0L; /* my internet address */
- INADDR gw_inaddr = 0L;
- INADDR lcl_netmask = (-1L);
-
- int ip_recv(int,char *); /* receive handler */
- static struct ip_protocol
- {
- int (*handler)(PACKET *,int,INADDR);
- int (*du_handler)(IP *);
- int protocol;
- } ip_protab[MAXIP];
- static int ip_protocols = 0;
- static int ip_handle = -1;
- PKTQUEUE *ip_qrecv = NULL;
- int ip_freecnt = 0;
-
- extern INETCUST *custom;
-
- INADDR iproute(INADDR);INADDR fixup_subnet_mask(INADDR, int);
-
-
- INADDR ip_myaddr()
- {
- return(lcl_inaddr);
- }
-
- int ip_init(void)
- {
- int nbuf;
- HADDR gw_haddr;
- int i;
-
-
- lcl_inaddr = custom->inaddr;
- gw_inaddr = custom->gateway;
- if(arp_init() < 0)
- {
- fprintf(stderr,"arp-init failed\n");
- return(FALSE);
- }
- if(gw_inaddr)
- {
- while((i=arp_in2haddr(gw_inaddr,gw_haddr)) == ARP_WAIT)
- {
- net_demux(FALSE,DEMUX);
- }
- if(i==ARP_OK)
- {
- #ifdef DEBUG
- printf("arp for gateway succeded\n");
- #endif
- arp_addgw(gw_inaddr,gw_haddr);
- }
- }
- if(custom->subnetbits)
- lcl_netmask = fixup_subnet_mask(lcl_inaddr,custom->subnetbits);
- if(ip_handle < 0) /* first time called, init net */
- {
- ip_handle = net_open(ET_IP,ip_recv);
- /* install demux function */
- if(ip_handle < 0) return(FALSE);
- if(!net_demux(TRUE,ip_demux))
- {
- net_release(ET_IP);
- ip_handle=-1;
- return(FALSE);
- }
- icmp_init();
- }
- nbuf = IP_NBUF;
- ip_qrecv = ip_q_create(nbuf,0);
- if(!ip_qrecv) return(FALSE);
- ip_freecnt = nbuf;
- return(TRUE);
- }
-
- int ip_exit(void)
- {
- while(ip_protocols)
- {
- ip_close(ip_protab[0].protocol);
- }
- ip_q_delete(ip_qrecv);
- net_demux(FALSE,ip_demux); /* uninstall demuxer */
- net_release(ET_IP);
- ip_handle = -1;
- #ifdef DEBUG
- printf("ip_exit\n");
- #endif
- arp_exit();
- return(TRUE);
- }
-
- int ip_open(int protocol,
- int (*prot_handler)(PACKET *,int,INADDR),
- int (*du_handler)(IP *))
- {
- register int i;
-
-
- if(ip_protocols >= MAXIP) return(FALSE);
- for(i=0; i<ip_protocols; i++)
- {
- if(ip_protab[i].protocol == protocol) return(FALSE);
- }
- ip_protab[ip_protocols].protocol = protocol;
- ip_protab[ip_protocols].handler = prot_handler;
- ip_protab[ip_protocols].du_handler = du_handler;
- ip_protocols++;
- return(TRUE);
- }
-
-
- int ip_close(int protocol)
- {
- register int i;
- for(i=0; i<ip_protocols; i++)
- {
- if(ip_protab[i].protocol == protocol)
- {
- for(;i<ip_protocols-1;i++)
- {
- ip_protab[i].protocol = ip_protab[i+1].protocol;
- ip_protab[i].handler = ip_protab[i+1].handler;
- ip_protab[i].du_handler = ip_protab[i+1].du_handler;
- }
- ip_protocols--;
- return(TRUE);
- }
- }
- return(FALSE);
- }
-
-
- int ip_recv(int length,char *pkt)
- {
- register int q_ok;
- void ip_demuxx(void);
-
- /* insert packet into ip receive queue */
- q_ok = ip_aq_putpkt(ip_qrecv,(PACKET *)pkt);
- if(q_ok) ip_demuxx();
- return(q_ok);
- }
-
- void ip_demuxx(void)
- {
- extern void pkt_mux(void);
-
- pkt_mux();
- }
-
- int ip_demux(void)
- {
- register PACKET *pkt;
- register IP *ip;
- register u_short csum;
- register int i;
- register int len;
- int loop;
-
- for(loop = 0;loop < 2; loop++)
- {
- pkt = ip_aq_getpkt(ip_qrecv); /* get packet */
- if(!pkt) return(FALSE); /* no packet there */
-
- #ifdef DEBUG
- printf("ip pkt recv ");
-
- #endif
-
- ip = ip_head(pkt);
-
- if(ip_version(ip) != IP_VERSION)
- {
- #ifdef DEBUG
- printf("bad version\n");
- #endif
- ip_free(pkt); /* bad version */
- return(FALSE);
- }
- csum = ip->chksum;
- ip->chksum = 0;
-
- if(chksum((u_short *)ip, ip_hdrlen(ip),0) != csum )
- {
- #ifdef DEBUG
- printf("bad chksum\n");
- #endif
- ip_free(pkt); /* bad checksum */
- return(FALSE);
- }
-
- ip->chksum = csum;
- if (ip->dst_inaddr != lcl_inaddr ) /* not for me */
- /*ip->dst_inaddr == 0xFFFFFFFFL)*/ /* or not broadcast */
- { /* packet not for me */
- #ifdef DEBUG
- printf("not for me (%lx)\n",ip->dst_inaddr);
- #endif
- ip_free(pkt); /* drop packet */
- return(FALSE);
- }
- if(ip->frag)
- {
- #ifdef DEBUG
- printf("ip packet FRAGMENTED\n");
- #endif
- ip_free(pkt); /* drop fragmented packet */
- return(FALSE);
- }
- len = ip->length - ip_hdrlen(ip);
- #ifdef DEBUG
- printf("protocol %2d\n",(int)ip->protocol);
- #endif
- for(i=0; i < ip_protocols; i++)
- {
- if(ip_protab[i].protocol == (int)ip->protocol)
- { /* add immediate reply entry */
- arp_add2tab(ip->src_inaddr,pkt->pkt_head.et_src);
- if(ip_protab[i].handler)
- {
- ip_protab[i].handler(pkt,len,ip->src_inaddr);
- break;
- }
- else
- {
- ip_free(pkt);
- break;
- }
- }
- }
- if(i >= ip_protocols)
- {
- /* no one wants packet */
- if(ip->dst_inaddr == lcl_inaddr)
- icmp_dstun(ip->src_inaddr,ip,ICMP_DSTPROT);
-
- ip_free(pkt);
- return (FALSE);
- }
- }
- return TRUE;
- }
-
-
- PACKET *ip_alloc(int length, int optlen)
- {
- register PACKET *pkt;
- register IP *ip;
-
- pkt = (PACKET *)net_pktalloc(ET_IP);
-
- if(!pkt)
- {
- Bconws("couldn't alloc IP packet\r");
- return(NULL);
- }
-
- ip = ip_head(pkt);
-
- /* internet header */
- ip->vh = (IP_VERSION << 4) + IP_HDR + (optlen + 3)/4;
- ip->tos = IP_TOS;
- ip->ident = 0;
- ip->frag = 0; /* don't fragment */
- ip->length = length;
- ip->ttl = IP_TTL;
- ip->chksum = 0;
- return(pkt);
- }
-
- int ip_free(PACKET *pkt)
- {
- int i;
- i = net_pktfree((char *)pkt);
- if(!i)
- {
- Bconws("couldn't free IP packet\r");
- }
- return(i);
- }
-
-
- int ip_send(int protocol, PACKET *pkt,int length, INADDR fhost)
- {
- register IP *ip;
- register int i;
- #ifdef DEBUG
- printf("ip_send %d octets\n",length);
- #endif
-
- #ifdef DEBUGF
- TRACE(">ip_send\n");
- #endif
-
-
- ip = ip_head(pkt);
- #ifdef DEBUGF
- TRACE("+>ip_send 1\n");
- #endif
-
- /* internet header */
- ip->protocol = protocol;
- ip->length = ip_hdrlen(ip) + length;
- ip->chksum = 0;
- ip->dst_inaddr = fhost;
- ip->src_inaddr = lcl_inaddr;
- ip->chksum = chksum((u_short *)ip, ip_hdrlen(ip),0);
- #ifdef DEBUGF
- TRACE("+>ip_send chksum\n");
- #endif
- pkt->pkt_head.et_type = ET_IP;
- net_getadr((int)sizeof(HADDR),pkt->pkt_head.et_src);
- #ifdef DEBUGF
- TRACE("+>ip_send getadr\n");
- #endif
- fhost = iproute(fhost);
- #ifdef DEBUGF
- TRACE("+>ip_send iproute\n");
- #endif
- while((i=arp_in2haddr(fhost,pkt->pkt_head.et_dest)) == ARP_WAIT)
- {
- evnt_timer(10,0);
- net_demux(FALSE,DEMUX);
- }
- #ifdef DEBUGF
- TRACE("+>ip_send arp done\n");
- #endif
- if(i != ARP_OK)
- {
- #ifdef DEBUGA
- printf("arp failed\n");
- #endif
- #ifdef DEBUGF
- TRACE("<ip_send, arp failed\n");
- #endif
- return(-1);
- }
- i = net_send(ip->length+(int)sizeof(ETH),(char *)pkt);
-
- #ifdef DEBUGF
- sprintf(str,"<ip_send,ret = %d\n",i);
- TRACE(str);
- #endif
-
- return(i);
- }
-
- /* called from ICMP */
- int ip_dudemux(IP *ip)
- {
- int i;
- for(i=0; i<ip_protocols; i++)
- {
- if(ip_protab[i].protocol == (int)ip->protocol)
- {
- if(ip_protab[i].du_handler)
- {
- ip_protab[i].du_handler(ip);
- return(TRUE);
- }
- }
- } /* no one wants packet */
- return(ip != NULL);
- }
-
- int ip_requeue(PACKET *pkt)
- {
- if(ip_freecnt > 2) /* keep min 2 free packets */
- {
- return(ip_aq_putpkt(ip_qrecv,pkt)); /* put packet again into receive queue */
- }
- return(FALSE);
- }
-
- INADDR iproute(INADDR fhost){register int i;
- #ifdef DEBUGF
- TRACE(">ip_route\n");
- #endif
- /* first check through the redirect table for this host */ for(i=0; i<REDIRTABLEN && redtab[i].dst_inaddr; i++) if(redtab[i].dst_inaddr == fhost)
- {#ifdef DEBUGF
- TRACE("<ip_route tabentry found\n");
- #endif
- return(redtab[i].gw_inaddr); } /* Check if it is on my net */ if(lcl_netmask == (-1L) || (lcl_inaddr & lcl_netmask) == (fhost & lcl_netmask))
- {
- #ifdef DEBUGF
- TRACE("<ip_route mask fit\n");
- #endif
- return(fhost);
- } if((fhost == 0xffffffffL)) /* broadcast */
- {
- #ifdef DEBUGF
- TRACE("<ip_route broadcast\n");
- #endif
- return(fhost);
- } /* The host isn't on a net I'm on,
- so send it to the default gateway */ if(!gw_inaddr)
- {#ifdef DEBUGF
- TRACE("<ip_route no gateway\n");
- #endif
- return(fhost);
- }
- #ifdef DEBUGF
- TRACE("<ip_route gateway\n");
- #endif
- return(gw_inaddr);}
-
- /* Fix the subnet mask given the IP address and the number of subnet bits.
- */
- INADDR fixup_subnet_mask(INADDR lcl_inaddr, int subnet_bits)
- {
- INADDR smask;
-
- /* initialize the bit field */
- if((lcl_inaddr & AMASK) == AADDR)
- smask = 0xFF000000L;
- else if((lcl_inaddr & BMASK) == BADDR)
- smask = 0xFFFF0000L;
- else if((lcl_inaddr & CMASK) == CADDR)
- smask = 0xFFFFFF00L;
-
- while(subnet_bits--)
- smask = (smask >> 1) | 0x80000000L;
- return(smask);
- }
-